﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MovieRental.Entities;
using MovieRental.DataInterfaces;
using MovieRental.BuisnessComponents.Base;
using MovieRental.BuisnessComponents.Exceptions;

namespace MovieRental.BuisnessComponents
{
    public class TemporaryDiscountComponent : BaseSetComponent<TemporaryDiscountInfo, Guid, ITemporaryDiscountRepository>
    {
        public TemporaryDiscountComponent(ITemporaryDiscountRepository repository)
            : base(repository)
        {

        }

        protected override bool Equals(TemporaryDiscountInfo discount1, TemporaryDiscountInfo discount2)
        {
            return (discount1.Value == discount2.Value && discount1.ValidUntil == discount2.ValidUntil);
        }

        public bool VerifyDiscountValue(double value)
        {
            return (value >= 0 && value < 100);
        }

        public bool VerifyDiscountValidUntil(DateTime date)
        {
            return (date.Date >= DateTime.Today);
        }

        public override void Verify(TemporaryDiscountInfo obj)
        {
            if (!VerifyDiscountValue(obj.Value))
                throw new FieldValueRangeException<double>(obj, "Value", 0, 100);
            if (!VerifyDiscountValidUntil(obj.ValidUntil))
                throw new FieldValueRangeException<DateTime>(obj, "ValidUntil", DateTime.Today, DateTime.MaxValue);
            base.Verify(obj);
        }

        public override TemporaryDiscountInfo Get(Guid id)
        {
            TemporaryDiscountInfo discount = base.Get(id);
            if (discount == null)
                return null;
            if (discount.ValidUntil.Date < DateTime.Today)
            {
                Repository.Delete(id);
                OnSourceUpdated();
                return null;
            }
            return discount;
        }

        private void DeleteIfUseless(Guid discountId)
        {
            var editionComponent = ComponentFactory.Instance.GetEditionComponent();
            if (!editionComponent.GetEditionsWithDiscount(discountId).Any())
            {
                Repository.Delete(discountId);
                OnSourceUpdated();
            }
        }

        public TemporaryDiscountInfo SetDiscount(EditionInfo edition, double value, DateTime until)
        {
            var editionComponent = ComponentFactory.Instance.GetEditionComponent();
            TemporaryDiscountInfo discount = new TemporaryDiscountInfo();
            discount.Value = value;
            discount.ValidUntil = until;
            var current = GetAvailableDiscount(edition);
            if (value == 0)
            {
                edition.DiscountId = Guid.Empty;
                editionComponent.AddOrUpdate(edition);
                DeleteIfUseless(current.Id);
                return null;
            }
            try
            {
                AddOrUpdate(discount);
            }
            catch (ItemDuplicateException<Guid> ex)
            {
                if (current != null && current.Id != ex.DuplicateObject.Id)
                    DeleteIfUseless(current.Id);
                edition.DiscountId = ex.DuplicateObject.Id;
                editionComponent.AddOrUpdate(edition);
                return (TemporaryDiscountInfo) ex.DuplicateObject;
            }
            edition.DiscountId = discount.Id;
            editionComponent.AddOrUpdate(edition);
            OnSourceUpdated();
            return discount;
        }

        public TemporaryDiscountInfo GetAvailableDiscount(EditionInfo edition)
        {
            return Get(edition.DiscountId);
        }

        public double GetAvailableDiscountValue(EditionInfo edition)
        {
            var discount = GetAvailableDiscount(edition);
            if (discount == null)
                return 0;
            else
                return discount.Value;
        }


        
    }
}
